using System.Diagnostics.CodeAnalysis;
using Unity.Burst;
using Unity.Jobs;
using UnityEngine;
using static Unity.Burst.SharedStatic<Burst.SharedStaticTests.SharedStaticUnmanagedUsing>;

namespace UnityEngine
{
    public class Debug
    {
        public static void Log(object message)
        {
        }
    }
}

namespace Unity
{
    namespace Jobs
    {
        [JobProducerType]
        public interface IJob
        {
            void Execute();
        }

        namespace LowLevel
        {
            namespace Unsafe
            {
                public class JobProducerTypeAttribute : Attribute
                {
                }
            }
        }
    }

    namespace Burst
    {
        public class BurstCompileAttribute : Attribute
        {
        }

        public class BurstDiscardAttribute : Attribute
        {
        }

        
        public readonly struct SharedStatic<T> where T : struct
        {
            public static SharedStatic<T> GetOrCreate<T1>(uint par1 = 0)
            {
                return new SharedStatic<T>();
            }

            public static SharedStatic<T> GetOrCreate<TContext, TSubContext>(uint par1 = 0)
            {
                return new SharedStatic<T>();
            }

            public static SharedStatic<T> GetOrCreate(Type par1, uint par2 = 0)
            {
                return new SharedStatic<T>();
            }
            
            public static SharedStatic<T> GetOrCreate(Type par1, Type par2, uint par3 = 0)
            {
                return new SharedStatic<T>();
            }
        }
    }

    namespace Collections
    {
        public struct NativeArray<T> : IDisposable, IEnumerable<T>, IEnumerable, IEquatable<NativeArray<T>>
            where T : struct
        {
            public void Dispose()
            {
                throw new NotImplementedException();
            }

            public IEnumerator<T> GetEnumerator()
            {
                throw new NotImplementedException();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }

            public bool Equals(NativeArray<T> other)
            {
                throw new NotImplementedException();
            }
        }
    }
}

namespace Burst.SharedStaticTests
{
    public struct SharedStaticUnmanagedUsing
    {
        private int a;
        private object obj;
    }
    
    public class SharedStaticCreateTests : MonoBehaviour
    {
        private void Start()
        {
            var test1 = new SharedStaticTest1();
            test1.Schedule().Complete();

            var test2 = new SharedStaticTest2();
            test2.Schedule().Complete();

            var test3 = new SharedStaticTest3();
            test3.Schedule().Complete();

            var test4 = new SharedStaticTest4();
            test4.Schedule().Complete();

            var test5 = new SharedStaticTest4();
            test4.Schedule().Complete();
        }
        
        [BurstCompile]
        public struct SharedStaticTest1 : IJob
        {
            public void Execute()
            {
                var sharedStatic0 = SharedStatic<int>.GetOrCreate(typeof(double));
            }
        }

        private struct SharedStaticMixed
        {
            private int a;
            public object obj;
        }

        [BurstCompile]
        public struct SharedStaticTest2 : IJob
        {
            public void Execute()
            {
                var sharedStatic1 = SharedStatic<SharedStaticMixed>.GetOrCreate<double>();
            }
        }
        
        private struct SharedStaticUnmanaged
        {
            private int a;
            private double b;
        }

        [BurstCompile]
        public struct SharedStaticTest3 : IJob
        {
            public void Execute()
            {
                var sharedStatic2 = SharedStatic<SharedStaticUnmanaged>.GetOrCreate<float, double>();
            }
        }

        [BurstCompile]
        public struct SharedStaticTest4 : IJob
        {
            public void Execute()
            {
                var sharedStatic3 = SharedStatic<int>.GetOrCreate(typeof(double), typeof(int));
            }
        }

        [BurstCompile]
        public struct SharedStaticTest5 : IJob
        {
            public void Execute()
            {
                var sharedStatic2 = GetOrCreate<float, double>();
            }
        }
    }
}